#ifndef COMMUNICATION_H
#define COMMUNICATION_H

#include "MySqlConn.h"
#include "AesCrypto.h"
#include "Buffer.h"
#include "Codec.h"
#include "Room.h"
#include "RoomList.h"

class Communication {
public:
    Communication();  // 实例化Communication: 初始化[MySQL连接对象], 初始化[连接Redis服务器的实例]
    ~Communication();

    void parseRequest(Buffer* buf); // 解析客户端发送过来的数据
    using sendCallback = function<void(string)>;
    using deleteCallback = function<void()>;
    void setCallback(sendCallback sendFunc, deleteCallback deleteFunc); // 设置回调: 发送数据的回调 + 释放资源的回调

    // 登录相关
    void handleAesFenFa(Message* reqMsg, Message& resMsg); // 处理客户端发来的[Aes密钥分发的Message]
    void handleRegister(Message* reqMsg, Message& resMsg); // 处理客户端发来的[注册用户的Message]
    void handleLogin(Message* reqMsg, Message& resMsg);    // 处理客户端发来的[用户登录的Message]
    // 房间选择
    void handleAddRoom(Message* reqMsg, Message& resMsg); // 处理客户端发来的[加入房间的Message]: _reqCode = AutoRoom / ManualRoom
    void handleLeaveRoom(Message* reqMsg, Message& resMsg); // 处理用户离开房间
    void handleSearchRoom(Message* reqMsg, Message& resMsg); // 处理搜索房间
    void handleGoodBye(Message* reqMsg);  // 处理客户端断开连接
    void handleGameOver(Message* reqMsg); // 处理游戏结束

    // 准备开始游戏
    void readyForPlay(string roomName, string data);
    // 转发数据: data为待转发的数据, roomName为数据的目标房间, userName为[期望将数据转发给房间内其他人]的玩家
    void notifyOtherPlayers(string data, string roomName, string userName);

    void dealCards(UserMap players); // 将[随机顺序的整副牌]发送给三个玩家
    void initCards();                // 洗牌
    pair<int, int> takeOneCard();    // 随机取出1张牌
    void restartGame(Message* reqMsg); // 重新开始游戏
    void startGame(string roomName, UserMap players); // 开始游戏
private:
    sendCallback _sendMessage;   // 发送数据
    deleteCallback _disconnect;  // 释放资源
    AesCrypto* _aes = nullptr;   // 对称加密算法Aes
    MySqlConn* _mysql = nullptr; // 连接MySQL的实例
    Room* _redis = nullptr;      // 连接Redis服务器的实例
    std::multimap<int, int> _cards;   // <花色, 点数>, multimap的键可重复
};

#endif //COMMUNICATION_H
